import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import '../models/todo_item.dart';
import '../models/category.dart' as model;
import 'auth_service.dart';

class ApiService {
  // Debug模式和Release模式的API地址配置
  static const String _debugBaseUrl = 'http://localhost:18886';
  static const String _releaseBaseUrl = 'https://liufq.cn/api';

  // 根据运行模式自动切换baseUrl
  static String get baseUrl => kDebugMode ? _debugBaseUrl : _releaseBaseUrl;

  // 401 错误回调，由 main.dart 设置
  static void Function()? onUnauthorized;

  /// 构建请求头（包含 Authorization）
  static Future<Map<String, String>> _buildHeaders() async {
    final headers = <String, String>{
      'Content-Type': 'application/json',
    };

    // 获取 token 并添加到请求头
    final token = await AuthService.getToken();
    if (token != null && token.isNotEmpty) {
      headers['Authorization'] = 'Bearer $token';
    }

    return headers;
  }

  /// 检查响应状态码，处理 401 错误
  static void _checkResponseStatus(int statusCode) {
    if (statusCode == 401) {
      print('🚫 Unauthorized (401) - Redirecting to login');
      onUnauthorized?.call();
      throw Exception('未授权，请重新登录');
    }
  }

  /// 打印请求日志
  static void _logRequest(String method, String url, {Map<String, dynamic>? body}) {
    print('🌐 API Request: $method $url');
    if (body != null) {
      print('📦 Request Body: ${json.encode(body)}');
    }
  }

  /// 打印响应日志
  static void _logResponse(int statusCode, dynamic body) {
    print('✅ API Response: $statusCode');
    if (body != null) {
      print('📥 Response Body: $body');
    }
  }

  /// 打印错误日志
  static void _logError(String message, dynamic error) {
    print('❌ API Error: $message');
    print('💥 Error Details: $error');
  }

  /// 获取 todo 列表
  static Future<List<TodoItem>> getTodoList({
    String? categoryId,
    bool? isCompleted,
    bool? isFavorite, // 是否关注
  }) async {
    var url = '$baseUrl/todo/list';
    final params = <String>[];
    if (categoryId != null) {
      params.add('categoryId=$categoryId');
    }
    if (isCompleted != null) {
      params.add('isCompleted=$isCompleted');
    }
    if (isFavorite != null) {
      params.add('isFavorite=$isFavorite');
    }
    if (params.isNotEmpty) {
      url += '?${params.join('&')}';
    }
    _logRequest('GET', url);

    try {
      final headers = await _buildHeaders();
      final response = await http.get(
        Uri.parse(url),
        headers: headers,
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        final jsonData = json.decode(responseBody);

        // 处理响应数据
        if (jsonData['code'] == 200) {
          final List<dynamic> data = jsonData['data'] as List<dynamic>;
          return data.map((item) => TodoItem.fromJson(item)).toList();
        } else {
          throw Exception(jsonData['message'] ?? '获取数据失败');
        }
      } else {
        throw Exception('请求失败: ${response.statusCode}');
      }
    } catch (e) {
      _logError('获取todo列表失败', e);
      throw Exception('网络请求异常: $e');
    }
  }

  /// 创建 todo
  static Future<TodoItem> createTodo(
    String title,
    String content, {
    String? categoryId,
  }) async {
    final url = '$baseUrl/todo/create';
    final requestBody = {
      'title': title,
      'content': content,
      if (categoryId != null && categoryId != '-1' && categoryId != '-2') 'categoryId': categoryId,
    };
    _logRequest('POST', url, body: requestBody);

    try {
      final headers = await _buildHeaders();
      final response = await http.post(
        Uri.parse(url),
        headers: headers,
        body: json.encode(requestBody),
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        final jsonData = json.decode(responseBody);

        // 处理响应数据
        if (jsonData['code'] == 200) {
          return TodoItem.fromJson(jsonData['data']);
        } else {
          throw Exception(jsonData['message'] ?? '创建失败');
        }
      } else {
        throw Exception('请求失败: ${response.statusCode}');
      }
    } catch (e) {
      _logError('创建todo失败', e);
      throw Exception('网络请求异常: $e');
    }
  }

  /// 更新 todo
  static Future<TodoItem> updateTodo(
    String id,
    String title,
    String content,
  ) async {
    final url = '$baseUrl/todo/$id';
    final requestBody = {
      'title': title,
      'content': content,
    };
    _logRequest('PUT', url, body: requestBody);

    try {
      final headers = await _buildHeaders();
      final response = await http.put(
        Uri.parse(url),
        headers: headers,
        body: json.encode(requestBody),
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        final jsonData = json.decode(responseBody);

        // 处理响应数据
        if (jsonData['code'] == 200) {
          return TodoItem.fromJson(jsonData['data']);
        } else {
          throw Exception(jsonData['message'] ?? '更新失败');
        }
      } else {
        throw Exception('请求失败: ${response.statusCode}');
      }
    } catch (e) {
      _logError('更新todo失败', e);
      throw Exception('网络请求异常: $e');
    }
  }

  /// 切换置顶状态
  static Future<TodoItem> toggleTop(String id, bool isTop) async {
    final url = '$baseUrl/todo/$id';
    final requestBody = {
      'isTop': isTop,
    };
    _logRequest('PUT', url, body: requestBody);

    try {
      final headers = await _buildHeaders();
      final response = await http.put(
        Uri.parse(url),
        headers: headers,
        body: json.encode(requestBody),
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        final jsonData = json.decode(responseBody);

        // 处理响应数据
        if (jsonData['code'] == 200) {
          return TodoItem.fromJson(jsonData['data']);
        } else {
          throw Exception(jsonData['message'] ?? '更新失败');
        }
      } else {
        throw Exception('请求失败: ${response.statusCode}');
      }
    } catch (e) {
      _logError('切换置顶状态失败', e);
      throw Exception('网络请求异常: $e');
    }
  }

  /// 更新关注状态
  static Future<TodoItem> updateFavorite(String id, bool isFavorite) async {
    final url = '$baseUrl/todo/$id';
    final requestBody = {
      'isFavorite': isFavorite,
    };
    _logRequest('PUT', url, body: requestBody);

    try {
      final headers = await _buildHeaders();
      final response = await http.put(
        Uri.parse(url),
        headers: headers,
        body: json.encode(requestBody),
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        final jsonData = json.decode(responseBody);

        // 处理响应数据
        if (jsonData['code'] == 200) {
          return TodoItem.fromJson(jsonData['data']);
        } else {
          throw Exception(jsonData['message'] ?? '更新失败');
        }
      } else {
        throw Exception('请求失败: ${response.statusCode}');
      }
    } catch (e) {
      _logError('更新星级评分失败', e);
      throw Exception('网络请求异常: $e');
    }
  }

  /// 删除 todo
  static Future<void> deleteTodo(String id) async {
    final url = '$baseUrl/todo/$id';
    _logRequest('DELETE', url);

    try {
      final headers = await _buildHeaders();
      final response = await http.delete(
        Uri.parse(url),
        headers: headers,
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        final jsonData = json.decode(responseBody);

        // 处理响应数据
        if (jsonData['code'] != 200) {
          throw Exception(jsonData['message'] ?? '删除失败');
        }
      } else {
        throw Exception('请求失败: ${response.statusCode}');
      }
    } catch (e) {
      _logError('删除todo失败', e);
      throw Exception('网络请求异常: $e');
    }
  }

  /// 更新 todo 分类
  static Future<TodoItem> updateCategory(String id, String categoryId) async {
    final url = '$baseUrl/todo/$id';
    final requestBody = {
      'categoryId': categoryId,
    };
    _logRequest('PUT', url, body: requestBody);

    try {
      final headers = await _buildHeaders();
      final response = await http.put(
        Uri.parse(url),
        headers: headers,
        body: json.encode(requestBody),
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        final jsonData = json.decode(responseBody);

        // 处理响应数据
        if (jsonData['code'] == 200) {
          return TodoItem.fromJson(jsonData['data']);
        } else {
          throw Exception(jsonData['message'] ?? '更新失败');
        }
      } else {
        throw Exception('请求失败: ${response.statusCode}');
      }
    } catch (e) {
      _logError('更新分类失败', e);
      throw Exception('网络请求异常: $e');
    }
  }

  /// 获取分类列表
  static Future<List<model.Category>> getCategoryList() async {
    final url = '$baseUrl/category/list?type=TODO';
    _logRequest('GET', url);

    try {
      final headers = await _buildHeaders();
      final response = await http.get(
        Uri.parse(url),
        headers: headers,
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        final jsonData = json.decode(responseBody);

        // 处理响应数据
        if (jsonData['code'] == 200) {
          final List<dynamic> data = jsonData['data'] as List<dynamic>;
          return data.map((item) => model.Category.fromJson(item)).toList();
        } else {
          throw Exception(jsonData['message'] ?? '获取数据失败');
        }
      } else {
        throw Exception('请求失败: ${response.statusCode}');
      }
    } catch (e) {
      _logError('获取分类列表失败', e);
      throw Exception('网络请求异常: $e');
    }
  }

  /// 创建分类
  static Future<model.Category> createCategory({
    required String name,
    String? parentId,
  }) async {
    final url = '$baseUrl/category/create';
    final requestBody = {
      'type': 'TODO',
      'name': name,
      if (parentId != null) 'parentId': parentId,
    };
    _logRequest('POST', url, body: requestBody);

    try {
      final headers = await _buildHeaders();
      final response = await http.post(
        Uri.parse(url),
        headers: headers,
        body: json.encode(requestBody),
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        final jsonData = json.decode(responseBody);

        // 处理响应数据
        if (jsonData['code'] == 200) {
          return model.Category.fromJson(jsonData['data']);
        } else {
          throw Exception(jsonData['message'] ?? '创建失败');
        }
      } else {
        throw Exception('请求失败: ${response.statusCode}');
      }
    } catch (e) {
      _logError('创建分类失败', e);
      throw Exception('网络请求异常: $e');
    }
  }

  /// 更新分类父级
  static Future<void> updateCategoryParent({
    required String categoryId,
    required String parentId,
  }) async {
    final url = '$baseUrl/category/$categoryId';
    final requestBody = {
      'parentId': parentId,
    };
    _logRequest('PUT', url, body: requestBody);

    try {
      final headers = await _buildHeaders();
      final response = await http.put(
        Uri.parse(url),
        headers: headers,
        body: json.encode(requestBody),
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        // 后端可能返回空响应体，直接认为成功
        if (responseBody.isEmpty) {
          return;
        }

        final jsonData = json.decode(responseBody);

        // 只检查是否成功，不处理返回值
        if (jsonData['code'] != 200) {
          throw Exception(jsonData['message'] ?? '更新失败');
        }
      } else {
        throw Exception('请求失败: ${response.statusCode}');
      }
    } catch (e) {
      _logError('更新分类父级失败', e);
      throw Exception('网络请求异常: $e');
    }
  }

  /// 拖拽分类排序
  /// dropType: before(前面), after(后面), inner(里面/成为子分类)
  static Future<void> dragCategory({
    required String categoryId,
    required String targetId,
    required String dropType, // before, after, inner
  }) async {
    final url = '$baseUrl/category/$categoryId/drag';
    final requestBody = {
      'targetId': targetId,
      'dropType': dropType,
    };
    _logRequest('PUT', url, body: requestBody);

    try {
      final headers = await _buildHeaders();
      final response = await http.put(
        Uri.parse(url),
        headers: headers,
        body: json.encode(requestBody),
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        // 后端可能返回空响应体，直接认为成功
        if (responseBody.isEmpty) {
          return;
        }

        final jsonData = json.decode(responseBody);

        // 只检查是否成功，不处理返回值
        if (jsonData['code'] != 200) {
          throw Exception(jsonData['message'] ?? '拖拽失败');
        }
      } else {
        throw Exception('请求失败: ${response.statusCode}');
      }
    } catch (e) {
      _logError('拖拽分类失败', e);
      throw Exception('网络请求异常: $e');
    }
  }

  /// 删除分类
  static Future<void> deleteCategory(String categoryId) async {
    final url = '$baseUrl/category/$categoryId';
    _logRequest('DELETE', url);

    try {
      final headers = await _buildHeaders();
      final response = await http.delete(
        Uri.parse(url),
        headers: headers,
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        // 后端可能返回空响应体，直接认为成功
        if (responseBody.isEmpty) {
          return;
        }

        // 尝试解析JSON响应
        try {
          final data = json.decode(responseBody);
          if (data['code'] != 200) {
            final error = data['message'] ?? '删除分类失败';
            _logError('Delete category failed', error);
            throw Exception(error);
          }
        } catch (e) {
          // 如果JSON解析失败但HTTP状态码是200，认为删除成功
          if (e is FormatException) {
            return;
          }
          rethrow;
        }
      } else {
        _logError('Delete category failed', 'HTTP ${response.statusCode}');
        throw Exception('删除分类失败: HTTP ${response.statusCode}');
      }
    } catch (e) {
      _logError('Delete category failed', e);
      rethrow;
    }
  }

  /// 更新分类名称
  static Future<void> updateCategoryName({
    required String categoryId,
    required String name,
  }) async {
    final url = '$baseUrl/category/$categoryId';
    final requestBody = {
      'name': name,
    };
    _logRequest('PUT', url, body: requestBody);

    try {
      final headers = await _buildHeaders();
      final response = await http.put(
        Uri.parse(url),
        headers: headers,
        body: json.encode(requestBody),
      );

      final responseBody = utf8.decode(response.bodyBytes);
      _logResponse(response.statusCode, responseBody);
      _checkResponseStatus(response.statusCode);

      if (response.statusCode == 200) {
        // 后端可能返回空响应体，直接认为成功
        if (responseBody.isEmpty) {
          return;
        }

        final jsonData = json.decode(responseBody);

        // 只检查是否成功，不处理返回值
        if (jsonData['code'] != 200) {
          throw Exception(jsonData['message'] ?? '更新失败');
        }
      } else {
        throw Exception('请求失败: ${response.statusCode}');
      }
    } catch (e) {
      _logError('更新分类名称失败', e);
      throw Exception('网络请求异常: $e');
    }
  }
}
